package cn.ctodb.commons.alioss;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.ListObjectsRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.aliyun.oss.model.ObjectMetadata;

import cn.ctodb.commons.pool.Object;

public class Client implements Object {
	private final Logger logger = LoggerFactory.getLogger(getClass());

	private OSSClient client;
	private String endpoint;
	private String accessKeyId;
	private String accessKeySecret;
	private String bucketName;

	public Client(String endpoint, String accessKeyId, String accessKeySecret) {
		this.endpoint = endpoint;
		this.accessKeyId = accessKeyId;
		this.accessKeySecret = accessKeySecret;
		init();
	}

	private void init() {
		client = new OSSClient(endpoint, accessKeyId, accessKeySecret);
	}

	/**
	 * 上传文件
	 *
	 * @param bucketName
	 *            文件的bucket
	 * @param fileName
	 *            上传文件名
	 * @param fileContent
	 *            上传文件字节数组
	 *
	 * @return 上传文件名
	 *
	 * @throws Exception
	 */
	public String upload(String fileName, byte[] fileContent) throws Exception {
		if (null == bucketName || null == fileName || null == fileContent)
			throw new Exception("AliOSSClient invalid arguement");
		String result;
		try {
			ObjectMetadata meta = new ObjectMetadata();
			meta.setContentDisposition("filename=\"" + fileName + "\"");
			client.putObject(bucketName, fileName, new ByteArrayInputStream(fileContent), meta);
			result = fileName;
		} catch (OSSException | ClientException e) {
			result = null;
			logger.error("阿里云文件上传出错", e);

		}
		return result;
	}

	/**
	 * 下载文件
	 *
	 * @param bucketName
	 *            文件的bucket
	 * @param fileName
	 *            下载文件名
	 * @return 返回下载文件字节数组
	 *
	 * @throws Exception
	 */
	public byte[] download(String fileName) throws Exception {
		if (null == bucketName || null == fileName)
			throw new Exception("AliOSSClient invalid arguement");

		byte[] fileContent;
		try {
			OSSObject object;
			object = client.getObject(new GetObjectRequest(bucketName, fileName));
			ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
			byte[] buff = new byte[100];
			int rc = 0;
			while ((rc = object.getObjectContent().read(buff, 0, 100)) > 0) {
				swapStream.write(buff, 0, rc);
			}
			fileContent = swapStream.toByteArray();
		} catch (OSSException | ClientException | IOException e) {
			logger.error("阿里云文件下载异常", e);
			fileContent = null;
		}
		return fileContent;
	}

	/**
	 * 删除文件
	 *
	 * @param bucketName
	 *            文件的bucket
	 * @param fileName
	 *            文件名
	 *
	 * @throws Exception
	 */
	public boolean delete(String fileName) throws Exception {
		if (null == bucketName || null == fileName)
			throw new Exception("AliOSSClient invalid arguement");

		boolean flag = true;
		try {
			client.deleteObject(bucketName, fileName);
		} catch (Exception e) {
			flag = false;
		}
		return flag;
	}

	/**
	 * 获取bucket文件列表
	 *
	 * @param bucketName
	 *            文件的bucket
	 * @return 文件名列表
	 *
	 * @throws Exception
	 */
	public List<String> getFileList() throws Exception {
		if (null == bucketName)
			throw new Exception("AliOSSClient invalid arguement");

		List<String> fileList = new ArrayList<String>();
		try {
			ObjectListing objectListing = client.listObjects(new ListObjectsRequest(bucketName).withMaxKeys(30));
			List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
			for (OSSObjectSummary s : sums) {
				fileList.add(s.getKey());
			}
		} catch (OSSException | ClientException e) {
			logger.error("获取bucket文件列表异常", e);
			fileList = null;
		}
		return fileList;
	}

	@Override
	public void destroy() {
		client.shutdown();
	}

}
